<?php
namespace App\Common\Cla\Rbac;

use App\Common as com;
use App\Common\Cla\Rbac\User as nameUser;
use App\Common\Cla\Rbac as nameRbac;

/**
 * @property nameRbac\User\DataStore $dataStore
 */
class User extends com\Cla\ClaBase\CommonOfId\Main {

	/**
	 * 用户类型
	 * @var int
	 */
	private int $_userType;

	/**
	 * 用户id
	 * @var int
	 */
	private int $_userId;

	/**
	 * User constructor.
	 * @param int $userType 用户类型
	 * @param int $userId 用户id
	 */
	public function __construct( int $userType, int $userId ) {
		$this->_userType = $userType;
		$this->_userId = $userId;
		//
		if( $this->_userId <= 0 ) throw com\Lib\Err\Exception::makeOfNew( '', com\Lib\Err\Code::$sysFunParamError );
		//
		parent::__construct( nameUser\DataStore::newOfThis( $this ) );
	}

	/**
	 * 获取用户类型
	 * @return int
	 */
	public function getUserType(  ) {
		return $this->_userType;
	}

	/**
	 * 获取用户id
	 * @return int
	 */
	public function getUserId(  ) {
		return $this->_userId;
	}

	/**
	 * 获取token KeyDb
	 * @return com\Lib\Cache\KeyDB
	 */
	private function getTokenSidKeyDb():com\Lib\Cache\KeyDB {
		return com\Lib\Cache\KeyDB::use( 'rbac.token' )->param( $this->getUserType(), $this->getUserId() );
	}

	/**
	 * 获取token对象
	 * @return com\Cla\Com\Token
	 */
	public function goToken() {
		return $this->goPool( __METHOD__, function(){
			if( $this->getTokenSidKeyDb()->has() ){
				// 存在
				$tokenObj = com\Cla\Com\Token::newClassOfUse( $this->getTokenSidKeyDb()->get() );
			}else{
				// 不存在->申请
				$tokenObj = com\Cla\Com\Token::apply();
				// 保存token
				$this->getTokenSidKeyDb()->set( $tokenObj->getAccessToken(), 1 );
				// 加入key关联列表
				$tokenObj->dataId()->addRelevanceKey( $this->getTokenSidKeyDb()->getKeyName() );
			}
			//
			return $tokenObj;
		} );
	}

	/**
	 * 检查是否已授权
	 * @param string $permissionSid 权限sid
	 * @return bool
	 */
	public function check( string $permissionSid ):bool {
		// 从token中检查权限
		$isCheck = $this->goToken()->auth()->check( $permissionSid );
		if( $isCheck !== null ) return $isCheck;
		// 检查
		$isCheck = $this->checkForce( $permissionSid );
		// 记录到token
		$this->goToken()->auth()->addCheckCache( $permissionSid, $isCheck );
		// 返回结果
		return $isCheck;
	}

	/**
	 * 检查是否已授权
	 * @param array $permissionSids 权限sids
	 * @return bool 其中一个不通过都会返回false
	 */
	public function checks( array $permissionSids ):bool {
		foreach( $permissionSids as $permissionSid ){
			if( ! $this->check( $permissionSid ) ){
				return false;
			}
		}
		//
		return true;
	}

	/**
	 * 检查是否已授权(强制)
	 * @param string $permissionSid 权限sid
	 * @return bool
	 */
	public function checkForce( string $permissionSid ):bool {
		// 获取
		$permissionId = com\Model\RbacPermission::gosDataUnit()->goFun()->getIdForSid( $permissionSid );
/*		$rbacPermissionDataUnit = com\Model\RbacPermission::dataUnit();
		$rbacPermissionDataUnit->goWhereDy()->sid( $permissionSid );
		$permissionId = $rbacPermissionDataUnit->value( 'id' );*/
		if( $permissionId <= 0 ) return false;
		// 检查单项权限
		$isBind = $this->gowPermission()->isBinds( [ $permissionId ] );
		if( $isBind ) return true;
		// 检查角色权限
		$isBind = $this->gowRole()->checkOfPermissionId( $permissionId );
		if( $isBind ) return true;
		// 默认拒绝
		return false;
	}

	/**
	 * @return nameRbac\User\Role
	 */
	public function gowRole():nameRbac\User\Role {
		return $this->goPool( __METHOD__, function(){
			return new nameRbac\User\Role( $this->dataStore );
		} );
	}

	/**
	 * @return nameRbac\User\Permission
	 */
	public function gowPermission():nameRbac\User\Permission {
		return $this->goPool( __METHOD__, function(){
			return new nameRbac\User\Permission( $this->dataStore );
		} );
	}

	/**
	 * @return nameRbac\User\Relation
	 */
	public function gowRelation():nameRbac\User\Relation {
		return $this->goPool( __METHOD__, function(){
			return new nameRbac\User\Relation( $this->dataStore );
		} );
	}

	/**
	 * 获取拥有的所有 permissionIds
	 * @return int[]
	 */
	public function getAllBindPermissionIds(  ):array {
		// 获取角色的权限ids
		$permissionIds = com\Cla\Rbac\Role::getPermissionIdsOfRoles( $this->gowRole()->getBindRoleIdsOfCache() );
		// 获取直接绑定的权限ids并合并
		$permissionIds = array_merge( $permissionIds, $this->gowPermission()->getBindPermissionIdsOfCache() );
		//
		return $permissionIds;
	}

	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	/**
	 * @param int $userType 用户类型
	 * @param int $userId 用户id
	 * @return $this
	 */
	public static function makeOfNew( int $userType, int $userId ):self {
	    return self::make( $userType, $userId );
	}

	/**
	 * @param int $userId
	 * @return $this
	 */
	public static function makeOfAdmin( int $userId ):self {
		return self::makeOfNew( com\Cla\User\Admin::$userType, $userId );
	}

	/**
	 * @param int $userId
	 * @return $this
	 */
	public static function makeOfCompany( int $userId ):self {
		return self::makeOfNew( com\Cla\User\Company::$userType, $userId );
	}

}
